﻿using System;
using System.Collections.Generic;
using System.Text;
using CSLive.ControlPanel.Editor;
using CommunityServer.Controls;
using CommunityServer.Components;
using CSLive.LiveID;
using System.Web;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Xml.XPath;
using System.Xml;
using System.Web.UI.WebControls;
using System.IO;

namespace CSLive.Controls
{
    public class LiveIdCreateUserSubForm : WrappedSubFormBase, ICSLiveControl
    {
        #region ICSLiveControl Members

        public Dictionary<string, Control> EditorControls
        {
            get
            {
                Dictionary<string, Control> dictionary;

                dictionary = new Dictionary<string, Control>
                {
                    {
                        "LiveID Create User Sub Form",
                        new Control("LiveId Create User Sub Form", "The Subform for the Create User page", false, 
                            "<CSLive:LiveIdCreateUserSubForm runat=\"server\" id=\"LiveIdSubForm\" CreateLiveIdUserButtonId=\"verifyLiveId\" StatusTextId=\"statusText\" VisibleAfterLiveIdVerified=\"false\"><FormTemplate><div class=\"CommonMessageWarning\"><asp:Label ID=\"LiveId_Signup\" runat=\"server\">LiveID Signup</asp:Label></div><asp:Panel runat=\"server\" DefaultButton=\"verifyLiveId\"><div class=\"CommonDescription\">To sign up using your LiveID, click the button bellow.</div><CSControl:WrappedLiteral runat=\"server\" ID=\"statusText\" Tag=\"Div\" CssClass=\"CommonValidationWarning\" /><div class=\"CommonFormFieldName\"><CSControl:ResourceButton id=\"verifyLiveId\" runat=\"server\" Text=\"Signup Using LiveID\" CausesValidation=\"false\" /></div></asp:Panel></FormTemplate></CSLive:LiveIdCreateUserSubForm>")
                    }
                }; 
                return dictionary;
            }
        }

        public string Name
        {
            get { return "Live ID Create User Sub Form"; }
        }

        public Uri DocsUri
        {
            get
            {
                return
                    new Uri(
                        "http://communityserverlive.com/Controls/Live-ID-Create-User-Sub-Form/default.aspx");
            }
        }

        public string Description
        {
            get { return "Windows Live ID Create User Sub Form"; }
        }

        public string Group
        {
            get { return "Live ID"; }
        }

        #endregion
        private IButton LiveIdButton;
        protected IText StatusText;
        private WindowsLiveLogin wll;
        private static readonly DateTime ExpireCookie = DateTime.Now.AddYears(-10);

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            string privacyurl = LiveConfiguration.Instance.getConfigSetting("Live ID SSO", "Privacy Page").ToString();
            if (privacyurl.StartsWith("~") || privacyurl.StartsWith("/"))
            {
                privacyurl = string.Format("{0}://{1}{2}", Context.Request.Url.Scheme, Context.Request.Url.Host,
                                            ResolveClientUrl(privacyurl));
            }
            wll = new WindowsLiveLogin(LiveConfiguration.Instance.getConfigSetting("Live ID SSO", "Application ID").ToString(),
                                        LiveConfiguration.Instance.getConfigSetting("Live ID SSO", "Secret").ToString(), null, false, privacyurl);
        }

        protected override void AttachChildControls()
        {
            LiveIdButton = CSControlUtility.Instance().FindButtonControl(this, CreateLiveIdUserButtonId);
            StatusText = CSControlUtility.Instance().FindTextControl(this, StatusTextId);
            if (LiveIdButton == null)
                throw new InvalidOperationException("LiveIdButton are required controls for rendering the LiveIdCreateUserForm");
            LiveIdButton.Click += new EventHandler(LiveIdButton_Click);
        }

        /// <summary>
        /// Gets or sets the login LiveId IButton id.
        /// </summary>
        /// <value>The login LiveId IButton id.</value>
        public virtual string CreateLiveIdUserButtonId
        {
            get { return (string)ViewState["CreateLiveIdUserButtonId"] ?? string.Empty; }
            set { ViewState["CreateLiveIdUserButtonId"] = value; }
        }

        /// <summary>
        /// Gets or sets the status text resource control id
        /// </summary>
        /// <value>The status text resource control id</value>
        public virtual string StatusTextId
        {
            get { return (string)ViewState["StatusTextId"] ?? string.Empty; }
            set { ViewState["StatusTextId"] = value; }
        }

        public bool VisibleAfterLiveIdVerified
        {
            get { return (bool)(ViewState["VisibleAfterOpenIdVerified"] ?? false); }
            set { ViewState["VisibleAfterOpenIdVerified"] = value; }
        }

        private void LiveIdButton_Click(object sender, EventArgs e)
        {
            Context.Response.Redirect(wll.GetLoginUrl("register"));
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            try
            {
                string action = Context.Request["action"];
                if (action == "delauth")
                {
                    //Attempt to extract the consent token from the response.
                    WindowsLiveLogin.ConsentToken token = wll.ProcessConsent(Context.Request.Form);
                    UriBuilder url = new UriBuilder("HTTPS", "livecontacts.services.live.com", 443);
                    url.Path = "/users/@L@" + Context.Request.Cookies["LiveID"].Value + "/REST/invitationsbyemail";
                    ServicePointManager.ServerCertificateValidationCallback += 
                        delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                        {
                            bool validationResult = true;
                            return validationResult;
                        };
                    string u = url.Uri.AbsoluteUri;
                    SendHttpRequest(ref u, token.Token);
                }
                else
                {
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void SendHttpRequest(ref string uriPath, string deltoken)
        {
            // Create HTTP request object.
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriPath);

            // Add the authentication header
            request.Headers["Authorization"] = "DelegatedToken dt=\"" + deltoken + "\"";
            // Only add the following Header if you can unzip/inflate the response automatically
            // otherwise the response will be unparsable and non XML
            request.Headers["Accept-Encoding"] = "gzip, deflate";
            request.Headers["Pragma"] = "No-Cache";

            request.CookieContainer = new CookieContainer();

            // Set the HTTP request method. For example, this can be POST, GET, and so on.
            request.Method = "GET";

            // Set the HTTP content type - IMPORTANT - This must be exactly as written here and is REQUIRED
            request.ContentType = "application/xml; charset=utf-8";
            // Invoke the HTTP request and get the response.
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlTextWriter writer = new XmlTextWriter(sw);
            writer.Formatting = Formatting.Indented;
            writer.Indentation = 4;
            writer.IndentChar = ' ';

            XPathDocument doc = new XPathDocument(response.GetResponseStream());
            XPathNavigator nav = doc.CreateNavigator();
            nav.WriteSubtree(writer);
            writer.Flush();
            writer.Close();

            Context.Response.SetCookie(new HttpCookie("LiveIdContactDetails", sb.ToString()));

            response.Close();
        }


        public override bool IsEnabled()
        {
            return true;
        }

        private void PopulateParentForm()
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(Context.Request.Cookies["LiveIdContactDetails"].Value);
            CreateUserForm parentForm = (CreateUserForm)this.HostForm;
            string passwordText = MemberRoleProfileProvider.Instance().Members.GeneratePassword(8, 2);

            TextBox email = CSControlUtility.Instance().FindControl(parentForm, parentForm.EmailAddressTextBoxId) as TextBox;
            TextBox username = CSControlUtility.Instance().FindControl(parentForm, parentForm.UserNameTextBoxId) as TextBox;
            TextBox email2 = CSControlUtility.Instance().FindControl(parentForm, parentForm.SecondEmailAddressTextBoxId) as TextBox;
            TextBox password = CSControlUtility.Instance().FindControl(parentForm, parentForm.PasswordTextBoxId) as TextBox;
            TextBox password2 = CSControlUtility.Instance().FindControl(parentForm, parentForm.SecondPasswordTextBoxId) as TextBox;
            IButton createAccount = CSControlUtility.Instance().FindButtonControl(parentForm, parentForm.CreateButtonId);
            CommunityServer.Controls.PlaceHolder passwordPlaceholder = CSControlUtility.Instance().FindControl(parentForm, parentForm.PasswordPlaceholderId) as CommunityServer.Controls.PlaceHolder;

            if (email != null && string.IsNullOrEmpty(email.Text) && xdoc.SelectSingleNode("/Contacts/Contact/PreferredEmail") != null)
                email.Text = xdoc.SelectSingleNode("/Contacts/Contact/PreferredEmail").Value;
            if (email2 != null && string.IsNullOrEmpty(email2.Text) && xdoc.SelectSingleNode("/Contacts/Contact/PreferredEmail") != null)
                email2.Text = xdoc.SelectSingleNode("/Contacts/Contact/PreferredEmail").Value;

            if (password != null)
            {
                password.Attributes.Add("value", passwordText);
                password.Visible = false;
            }
            if (password2 != null)
            {
                password2.Attributes.Add("value", passwordText);
                password2.Visible = false;
            }

            if (passwordPlaceholder != null)
                passwordPlaceholder.Visible = false;

            if (createAccount != null && createAccount.Attributes["disabled"] != null && email != null && email2 != null && username != null &&
                    xdoc.SelectSingleNode("/Contacts/Contact/PreferredEmail") != null)
                createAccount.Attributes.Remove("disabled");

            this.Visible = VisibleAfterLiveIdVerified;
        }

        public override void ApplyChangesAfterCommit(object activeObject)
        {
            User user = activeObject as User;
            user.SetExtendedAttribute("LiveID", Context.Request.Cookies["LiveID"].Value);
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(Context.Request.Cookies["LiveIdContactDetails"].Value);
            if (xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/FirstName") != null)
                user.Profile.CommonName = xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/FirstName").Value;
            if (xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/FirstName") != null && xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/LastName") != null)
                user.Profile.CommonName += " ";
            if (xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/LastName") != null)
                user.Profile.CommonName = user.Profile.CommonName + xdoc.SelectSingleNode("/Contacts/Contact/Profiles/Personal/LastName").Value;
            base.ApplyChangesAfterCommit(activeObject);
        }

        public override void ApplyChangesBeforeCommit(object activeObject)
        {
            User user = activeObject as User;

            if (user != null && Globals.IsNullorEmpty(user.Password))
                user.Password = MemberRoleProfileProvider.Instance().Members.GeneratePassword(8, 2);

            base.ApplyChangesBeforeCommit(activeObject);
        }
    }
}
